package com.abc.recycling.service.impl;

import com.abc.recycling.model.RecyclingStation;
import com.abc.recycling.repository.RecyclingStationRepository;
import com.abc.recycling.service.RecyclingStationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.PageImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class RecyclingStationServiceImpl implements RecyclingStationService {

    private static final double LAT_PER_KM = 0.009;
    private static final double LON_PER_KM = 0.0115;

    private final RecyclingStationRepository stationRepository;

    @Override
    public List<RecyclingStation> findStations(String keyword) {
        if (StringUtils.hasText(keyword)) {
            return stationRepository.findByNameContainingOrAddressContaining(keyword, keyword);
        }
        return stationRepository.findAll();
    }

    @Override
    public RecyclingStation findById(Long id) {
        return stationRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("回收站不存在"));
    }

    @Override
    @Transactional
    public void create(RecyclingStation station) {
        validateStation(station);
        station.setStatus(1);
        station.setCreateTime(LocalDateTime.now());
        station.setUpdateTime(LocalDateTime.now());
        stationRepository.save(station);
    }

    @Override
    @Transactional
    public void update(RecyclingStation station) {
        if (station.getId() == null) {
            throw new RuntimeException("回收站ID不能为空");
        }
        validateStation(station);
        
        RecyclingStation existingStation = findById(station.getId());
        existingStation.setName(station.getName());
        existingStation.setAddress(station.getAddress());
        existingStation.setDescription(station.getDescription());
        existingStation.setLatitude(station.getLatitude());
        existingStation.setLongitude(station.getLongitude());
        existingStation.setContactPhone(station.getContactPhone());
        existingStation.setContactPerson(station.getContactPerson());
        existingStation.setBusinessHours(station.getBusinessHours());
        existingStation.setAcceptableItems(station.getAcceptableItems());
        existingStation.setUpdateTime(LocalDateTime.now());
        
        stationRepository.save(existingStation);
    }

    @Override
    @Transactional
    public void updateStatus(Long id, Integer status) {
        if (status == null || (status != 0 && status != 1)) {
            throw new RuntimeException("无效的状态值");
        }
        
        RecyclingStation station = findById(id);
        station.setStatus(status);
        station.setUpdateTime(LocalDateTime.now());
        stationRepository.save(station);
    }

    @Override
    @Transactional
    public void delete(Long id) {
        RecyclingStation station = findById(id);
        stationRepository.delete(station);
    }

    @Override
    public Page<RecyclingStation> searchStations(String keyword, Pageable pageable) {
        try {
            if (StringUtils.hasText(keyword)) {
                return stationRepository.findByNameContainingOrAddressContaining(
                    keyword, keyword, pageable);
            } else {
                return stationRepository.findAll(pageable);
            }
        } catch (Exception e) {
            log.error("搜索回收站失败: {}", e.getMessage());
            return new PageImpl<>(new ArrayList<>(), pageable, 0);
        }
    }

    @Override
    public List<RecyclingStation> findNearbyStations(Double latitude, Double longitude, Integer radius) {
        if (latitude == null || longitude == null || radius == null) {
            throw new RuntimeException("位置参数不能为空");
        }
        
        try {
            // 使用简单的经纬度范围查询
            double latRange = radius * 0.009; // 大约1km对应0.009度
            double lonRange = radius * 0.009 / Math.cos(Math.toRadians(latitude));
            
            return stationRepository.findNearbyStations(
                latitude - latRange,
                latitude + latRange,
                longitude - lonRange,
                longitude + lonRange
            );
        } catch (Exception e) {
            log.error("查找附近回收站失败: {}", e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public Page<RecyclingStation> findAll(Pageable pageable) {
        try {
            return stationRepository.findAll(pageable);
        } catch (Exception e) {
            log.error("获取所有回收站失败: {}", e.getMessage());
            return new PageImpl<>(new ArrayList<>(), pageable, 0);
        }
    }

    @Override
    public List<RecyclingStation> getNearbyStations(Double latitude, Double longitude, Integer radius) {
        try {
            log.info("查找附近回收站: lat={}, lng={}, radius={}", latitude, longitude, radius);
            
            // 计算经纬度范围
            double latRange = radius * LAT_PER_KM;  // 每公里对应的纬度差
            double lonRange = radius * LON_PER_KM;  // 每公里对应的经度差
            
            // 查询在范围内的回收站
            List<RecyclingStation> stations = stationRepository.findNearbyStations(
                latitude - latRange,
                latitude + latRange,
                longitude - lonRange,
                longitude + lonRange
            );
            
            // 过滤掉已关闭的回收站
            stations = stations.stream()
                .filter(station -> station.getStatus() != null && station.getStatus() == 1)
                .collect(Collectors.toList());
                
            // 计算实际距离并排序
            stations.forEach(station -> {
                double distance = calculateDistance(
                    latitude, longitude,
                    station.getLatitude(), station.getLongitude()
                );
                // 将距离临时存储在description字段中
                station.setDescription(String.format("%.1f", distance));
            });
            
            // 按距离排序
            stations.sort((a, b) -> {
                double distA = Double.parseDouble(a.getDescription());
                double distB = Double.parseDouble(b.getDescription());
                return Double.compare(distA, distB);
            });
            
            return stations;
        } catch (Exception e) {
            log.error("查找附近回收站失败: {}", e.getMessage());
            return new ArrayList<>();
        }
    }

    // 使用Haversine公式计算两点之间的距离(单位:公里)
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        double R = 6371; // 地球半径(公里)
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);
        double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                   Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                   Math.sin(dLon/2) * Math.sin(dLon/2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        return R * c;
    }

    private void validateStation(RecyclingStation station) {
        if (!StringUtils.hasText(station.getName())) {
            throw new RuntimeException("回收站名称不能为空");
        }
        if (!StringUtils.hasText(station.getAddress())) {
            throw new RuntimeException("回收站地址不能为空");
        }
        if (station.getLatitude() == null || station.getLongitude() == null) {
            throw new RuntimeException("回收站经纬度不能为空");
        }
        if (!StringUtils.hasText(station.getContactPhone())) {
            throw new RuntimeException("联系电话不能为空");
        }
        if (!StringUtils.hasText(station.getBusinessHours())) {
            throw new RuntimeException("营业时间不能为空");
        }
    }
} 